/* 
 * File:   02_FilesystemReading.cpp
 * Author: pkv
 *
 * Created on August 7, 2011, 7:59 AM
 */

#include "core/Filesystem.h"

#include <cstdlib>
#include <sstream>
#include <iostream>
#include <fstream>

using namespace std;

/*
 * Runs a test to see if the filesystem is working correctly.  Attempts to load
 * a file both from a relative path and from an archive, and checks the content. 
 */
int main(int argc, char** argv)
{
    // Create a local filesystem object and mount the base directory
    Filesystem fs;
    fs.mount(fs.getBaseDir());
    
    cout << "Loading a local file for reading...";
    {
        // Try to load a local file for reading
        std::auto_ptr<std::istream> inputPtr = fs.openRead("02_Filesystem_Payload1.txt");
        std::istream &input = *inputPtr;

        // Read the contents
        std::string line;
        getline(input, line);

        // Verify the contents
        if (line.compare("READ_TEST1"))
        {
            cerr << "Failed to read local file correctly." << endl;
            return 1;
        }

        // Closing the file (can be done automatically too)
        inputPtr.reset();
    }
    cout << "success." << endl;

    cout << "Loading a non-existent file for reading...";
    {
        // Try to load an archived file before it is in the search path
        std::auto_ptr<std::istream> inputPtr = fs.openRead("02_Filesystem_Fake.txt");
        std::istream &input = *inputPtr;

        // Read the contents
        std::string line;
        getline(input, line);

        // The buffer should still be empty
        if (!line.empty())
        {
            cerr << "Read non-empty string from empty file: " << line << endl;
        }

        // The IOstream should now report EOF
        if (!input.eof())
        {
            cerr << "Reported success on loading nonexistent file." << endl;
            return 1;
        }
    }
    cout << "success." << endl;

    cout << "Loading an archived file for reading...";
    {
        // Add an archive to search path
        std::string archivePath = fs.getBaseDir();
        archivePath += "02_Filesystem_Payload2.zip";
        fs.mount(archivePath, "");

        // Try to load an archived file that is in the search path
        std::auto_ptr<std::istream> inputPtr = fs.openRead("02_Filesystem_Payload2.txt");
        std::istream &input = *inputPtr;

        // Read the contents
        std::string line;
        getline(input, line);

        // Verify the contents
        if (line.compare("READ_TEST2"))
        {
            cerr << "Failed to read local file correctly." << endl;
            return 1;
        }

        // Closing the file (can be done automatically too)
        inputPtr.reset();
    }
    cout << "success." << endl;

    cout << "Opening a local file for writing...";
    {
        // Set the write directory, then open a local file for writing
        fs.setWriteDir(fs.getBaseDir());
        std::auto_ptr<std::ostream> outputPtr = fs.openWrite("02_Filesystem_Payload3.txt");
        std::ostream &output = *outputPtr;

        // Write some contents
        output << "WRITE_TEST1" << endl;

        // Close the file
        outputPtr.reset();
    }
    cout << "success." << endl;

    cout << "Opening a local file for appending...";
    {
        // Try to open a local file for appending
        fs.setWriteDir(fs.getBaseDir());
        std::auto_ptr<std::ostream> outputPtr = fs.openWrite("02_Filesystem_Payload3.txt", true);
        std::ostream &output = *outputPtr;

        // Write some contents
        output << "WRITE_TEST2" << endl;

        // Close the file
        outputPtr.reset();
    }
    cout << "success." << endl;

    cout << "Verifying contents of written file...";
    {
        // Verify that file was created
        if (!fs.exists("02_Filesystem_Payload3.txt"))
        {
            cerr << "Writing to file did not create file." << endl;
            return 1;
        }

        // Open the file through stdio and verify the contents
        std::string filePath = fs.getBaseDir();
        filePath += "02_Filesystem_Payload3.txt";
        ifstream fin(filePath.c_str());

        // Read and verify the contents of the file
        std::string line;
        
        getline(fin, line);
        if (line.compare("WRITE_TEST1"))
        {
            cerr << "Failed to write to file correctly: " << line << endl;
            return 1;
        }

        getline(fin, line);
        if (line.compare("WRITE_TEST2"))
        {
            cerr << "Failed to append to file correctly: " << line << endl;
            return 1;
        }

        getline(fin, line);
        if (!line.empty())
        {
            cerr << "Failed to reach end of file correctly: " << line << endl;
            return 1;
        }
        
        // Close the file
        if (!fin.eof())
        {
            cerr << "Failed to close written file correctly." << endl;
            return 1;
        }
        fin.close();

        // Delete the file
        fs.del("02_Filesystem_Payload3.txt");

        // Verify that it no longer exists
        if (fs.exists("02_Filesystem_Payload3.txt"))
        {
            cerr << "Deleting file did not remove file." << endl;
            return 1;
        }
    }
    cout << "success." << endl;

    return 0;
}

